Skip to content

Match QEMU audio rates to selected Mac devices - #283

Merged
themartiano merged 4 commits into
omacom:mainfrom
stevederico:fix/audio-host-sample-rate
Oct 2, 2026
Merged

themartiano merged 4 commits into
omacom:mainfrom
stevederico:fix/audio-host-sample-rate

Conversation

@stevederico

@stevederico stevederico commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

What changed and why

Addresses #265: guest audio is reported to play too fast when the host output uses a different rate from QEMU's default mixer.

At launch, query CoreAudio through the bundled native helper and set QEMU's input and output frequencies independently. Each query follows the effective SDL device selected in Omarchy, including duplicate-name suffixes, and uses that direction's Mac default when a saved device is disconnected. Unavailable or invalid rates fall back to 48000 Hz independently. No new dependencies or runtime pins.

This is a launch-time mitigation. The underlying timing or resampling fault has not been isolated, and rates remain fixed until the VM restarts. Changing a device or its rate during a session can require a restart.

Testing

  • make test-shell-qemu-memory-contract: passed, including the Swift tests and the launcher contract. Coverage includes selected routes, duplicate SDL names, direction-specific defaults, disconnected-device fallback, rate validation, and independent query failures.
  • make test: passed on macOS, including a rerun after resolving conflicts with current main. Staged-QEMU lock inheritance was skipped because the staged runtime binary is absent.
  • bash -n macos/run-qemu-gpu.sh macos/Tests/qemu-memory-contract.test.sh and git diff --check: passed.
  • Built helper queries with no host audio devices return status 1 with no rate; an invalid direction returns usage status 64.
  • Actual playback, microphone capture, and a full app/runtime build were not verified for the correction; this host exposes no audio devices.

Original author measurements on an M3 MacBook Air running macOS 15.6 used a 20.000-second stereo tone, host-side monotonic timing over SSH, and 8–10 runs per condition:

Mac output rate Before With matched mixer
48000 Hz 19.033 / 19.090 s 20.158 s (SD 0.019)
44100 Hz 20.013 / 19.867 s 20.161 s (SD 0.017)

These results were reported by the original author and were not independently reproduced here. Detection at 88200 and 96000 Hz was reported, but playback validation was limited to 44100 and 48000 Hz. The author also reported residual drift at 96000 Hz on an unpatched build even with matched rates. Earlier issue measurements saying a matched 48000 Hz mixer still drifted remain to be reconciled with the later results.

QEMU's audiodev defaults to a 44100 Hz mixer regardless of the host
output device. When the Mac's default output device runs at any other
rate, the guest's PCM stream is drained at the wrong speed and playback
drifts. At 48000 Hz, the macOS built-in default, a 20.000 s clip plays
in about 19.0 s.

Query CoreAudio for the default output device's nominal rate and pass it
as out.frequency/in.frequency so the mixer and the device agree. Fall
back to 48000 when the query cannot answer.

Measured with a 20.000 s tone played by pw-play in the guest and timed
from the host over an SSH forward, so the guest clock is outside the
measurement path (8-10 runs per condition):

  device 48000, before: 19.033 s / 19.090 s (about 4.8% fast)
  device 48000, after:  20.158 s (sd 0.019)
  device 44100, before: 20.013 s / 19.867 s
  device 44100, after:  20.161 s (sd 0.017)

Both rates now land on the same figure, so playback speed no longer
depends on the host device rate. The residual 0.16 s is constant pw-play
startup and is present in every configuration.
The launcher now passes the Mac output device's rate to the audiodev, so
the exact -audiodev line the test pinned no longer matched. Give the test
a system_profiler shim that reports a 44100 Hz default output device and
expect out.frequency and in.frequency at that rate, which also checks the
detection instead of the 48000 fallback.
digital-brew pushed a commit to digital-brew/try-omarchy that referenced this pull request Sep 29, 2026
QEMU's audiodev opens its mixer at 44100 Hz regardless of the Mac's output
device. With the device at macOS's default 48000 Hz the guest's PCM stream is
drained at the wrong speed and every app plays about 5 percent fast and
sharp. Read the default output device's nominal rate from CoreAudio through
system_profiler and pass it as out.frequency and in.frequency, falling back
to 48000 when the query cannot answer. From omacom#283.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018W8fhTegW8d16zpAjRpsT9
digital-brew pushed a commit to digital-brew/try-omarchy that referenced this pull request Sep 29, 2026
QEMU's audiodev opens its mixer at 44100 Hz regardless of the Mac's output
device. With the device at macOS's default 48000 Hz the guest's PCM stream is
drained at the wrong speed and every app plays about 5 percent fast and
sharp. Read the default output device's nominal rate from CoreAudio through
system_profiler and pass it as out.frequency and in.frequency, falling back
to 48000 when the query cannot answer. From omacom#283.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018W8fhTegW8d16zpAjRpsT9
@themartiano themartiano changed the title Match the QEMU audio mixer to the Mac output device rate Match QEMU audio rates to selected Mac devices Oct 2, 2026
@themartiano
themartiano merged commit 226ca68 into omacom:main Oct 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants